// 混入方法
function _mixin(
  target: IndexObject,
  ...mixinObj: any[]
): IndexObject | boolean {
  if (target == null) {
    console.warn("请检查混入的对象参数是否正确。");
    return false;
  }
  mixinObj.forEach((obj) => {
    // 遍历混入对象的可枚举属性
    Object.keys(obj).forEach((key) => {
      target[key] = obj[key];
    });
  });
  return target;
}
// 抓取DOM方法
function _getSingleDom(
  selector: string | undefined | Element
): Element | undefined {
  if (!selector) {
    console.warn("输入的选择器为空，请检查输入的选择器是否正确。");
    return;
  }
  if (typeof selector !== "string") {
    return selector;
  }
  const elem = document.querySelector(selector);
  if (elem) {
    return elem;
  }
  console.warn("没有获取到的元素，请检查输入的选择器是否正确。");
}
// 分页器类
class SplitPager implements ISplitPager{
  el: Element | undefined;
  options: PagerOptions = {};
  currentPage: number = this.options.currentPage || 1;
  pageScope: number[] = [];
  static version = "0.0.4";
  static mark = "p-mark";
  static bannedStyleName = "pager-banned";
  static activeStyleName = 'pager-active';
  protected prevElem?: Element;
  protected nextElem?: Element;
  protected firstElem?: Element;
  protected lastElem?: Element;
  protected normalElem: Element[] = [];
  protected htmlString = "";
  // 默认设置
  protected defaultOptions = {
    el: "",
    totalPage: 10,
    showPage: 5,
    currentPage: 1,
    pageQuery: "",
  };
  // 页面模板
  protected pageTemplate = {
    prevButton:
      '<button class = "pager-base pager-prev" p-mark = "prev">back</button>',
    nextButton:
      '<button class = "pager-base pager-next" p-mark = "next">next</button>',
    firstButton:
      '<button class = "pager-base pager-first" p-mark = "first">首页</button>',
    lastButton:
      '<button class = "pager-base pager-last" p-mark = "last">末页</button>',
    pageButton: '<button class = "pager-base pager-normal">?</button>',
  };
  private rootPath = "";
  // 构造函数
  constructor(options: PagerOptions) {
    this.initOptions(options);
    this.initDom();
    this.initRootPath();
    this.spliceHtml();
    this.mountDom();
    this.setDomRef();
    this.calNumberScope();
    this.updateDomContent();
    this.setButtonAuthority();
    this.bindEvents();
  }
  // 初始化设置参数
  protected initOptions(options: PagerOptions) {
    _mixin(this.options, this.defaultOptions, options);
  }
  // 初始化DOM元素
  protected initDom() {
    this.el = _getSingleDom(this.options.el) as HTMLElement;
  }
  // 初始化根路径
  protected initRootPath() {
    this.rootPath = location.pathname;
  }
  // 拼接html字符串
  protected spliceHtml() {
    let htmlContent =
      this.pageTemplate.firstButton + this.pageTemplate.prevButton; // 首页按钮+后退按钮
    for (let i = 0; i < (this.options.showPage as number); i++) {
      // 拼接分页部分
      htmlContent = htmlContent + this.pageTemplate.pageButton;
    }
    htmlContent =
      htmlContent + this.pageTemplate.nextButton + this.pageTemplate.lastButton;
    this.htmlString = htmlContent;
  }
  // 挂载DOM元素
  protected mountDom() {
    if (typeof this.el === "undefined") {
      throw new Error("挂载DOM阶段失败，未找到真实存在的DOM元素。");
    }
    this.el.innerHTML = this.htmlString;
  }
  // 设置DOM引用
  protected setDomRef() {
    const elemChildren = (this.el as HTMLElement).children;
    const hashMap: IndexObject = {
      prev: "prevElem",
      next: "nextElem",
      first: "firstElem",
      last: "lastElem",
    };
    Array.prototype.forEach.call(elemChildren, (elem) => {
      let markAttr = elem.getAttribute(SplitPager.mark);
      if (markAttr != null) {
        (this as any)[hashMap[markAttr]] = elem;
      } else {
        this.normalElem.push(elem);
      }
    });
  }
  // 计算数字范围
  protected calNumberScope() {
    if (
      (this.options.showPage as number) > (this.options.totalPage as number)
    ) {
      throw new Error(
        "输入的总页数小于展示页数，请检查输入的参数页数是否合理。"
      );
    }
    this.pageScope = []; // 初始化页码范围
    let currentPage: number = this.currentPage;
    let { totalPage, showPage } = this.options; // 解构出总页数及展示按钮页数
    if (!totalPage || !showPage) {
      // 类型检查
      console.warn("请检查参数 showPage 或 totalPage 是否被正确输入。");
      return;
    }
    let start1 = Math.max(
      currentPage - Math.round((showPage as number) / 2),
      1
    );
    let end1 = Math.min(start1 + showPage - 1, totalPage);
    let end2 = Math.min(currentPage + Math.round(showPage / 2) - 1, totalPage);
    let start2 = Math.max(end2 - showPage + 1, 1);
    let start = Math.min(start1, start2);
    let end = Math.max(end1, end2);
    for (let i = start; i <= end; i++) {
      this.pageScope.push(i);
    }

    // console.log(this.pageScope, this.currentPage);
    // if (this.currentPage === 1) {
    //   // 当前为首页时
    //   let endPage: number = Math.min(
    //     this.options.showPage as number,
    //     this.options.totalPage as number
    //   );
    //   for (let i = 1; i <= endPage; i++) {
    //     this.pageScope.push(i);
    //   }
    //   return;
    // }
    // if (this.currentPage === this.options.totalPage) {
    //   // 到最后一页时
    //   let startPage: number = Math.max(
    //     this.options.totalPage - (this.options.showPage as number),
    //     1
    //   );
    //   for (let i = startPage; i <= this.options.totalPage; i++) {
    //     this.pageScope.push(i);
    //   }
    //   return;
    // }
    // // 正常情况时
    // if ((this.options.showPage as number) % 2 !== 0) {
    //   // 展示奇数个
    //   let half: number = Math.floor((this.options.showPage as number) / 2);
    //   let startPage: number = Math.max(this.currentPage - half, 1);
    //   let endPage: number = Math.min(
    //     this.currentPage + half,
    //     this.options.totalPage as number
    //   );
    //   for (let i = startPage; i <= endPage; i++) {
    //     this.pageScope.push(i);
    //   }
    // } else {
    //   // 展示个数为偶数
    //   let half: number = Math.floor((this.options.showPage as number) / 2);
    //   let startPage: number = Math.max(this.currentPage - half + 1, 1);
    //   let endPage: number = Math.min(
    //     this.currentPage + half,
    //     this.options.totalPage as number
    //   );
    //   for (let i = startPage; i <= endPage; i++) {
    //     this.pageScope.push(i);
    //   }
    // }
  }
  // 更新DOM内容
  protected updateDomContent() {
    // 去除所有的active样式
    this.removeElemStyle(SplitPager.activeStyleName, ...this.normalElem);
    for (let i = 0; i < this.normalElem.length; i++) {
      let value: string = this.pageScope[i].toString();
      this.normalElem[i].textContent = value;
      // 设置动态样式
      if (value === this.currentPage.toString()) this.addElemStyle(SplitPager.activeStyleName, this.normalElem[i]);
      (this.normalElem[i] as HTMLElement).dataset.pagerValue = value;
    }
  }
  // 设定按钮权限
  protected setButtonAuthority() {
    if (this.currentPage === 1) {
      // 到首页
      this.firstElem?.setAttribute("disabled", "");
      this.prevElem?.setAttribute("disabled", "");
      this.addElemStyle(SplitPager.bannedStyleName, this.firstElem, this.prevElem);
      this.addElemStyle(SplitPager.bannedStyleName + ':hover', this.firstElem, this.prevElem);// ！移除hover样式
    } else {
      this.firstElem?.removeAttribute("disabled");
      this.prevElem?.removeAttribute("disabled");
      this.removeElemStyle(SplitPager.bannedStyleName, this.firstElem, this.prevElem);
      this.removeElemStyle(SplitPager.bannedStyleName + ':hover', this.firstElem, this.prevElem);
    }
    if (this.currentPage === this.options.totalPage) {
      this.lastElem?.setAttribute("disabled", "");
      this.nextElem?.setAttribute("disabled", "");
      this.addElemStyle(SplitPager.bannedStyleName, this.lastElem, this.nextElem);
    } else {
      this.lastElem?.removeAttribute("disabled");
      this.nextElem?.removeAttribute("disabled");
      this.removeElemStyle(SplitPager.bannedStyleName, this.lastElem, this.nextElem);
    }
  }
  // 绑定事件方法
  protected bindEvents() {
    let _this = this;
    function firstHandle() {
      // 首页绑定方法
      _this.jumpToPage(1);
    }
    function prevHandle() {
      // 返回上一页方法
      _this.jumpToPage(_this.currentPage - 1);
    }
    function nextHandle() {
      // 前往下一页方法
      _this.jumpToPage(_this.currentPage + 1);
    }
    function lastHandle() {
      // 前往最后一页方法
      _this.jumpToPage(_this.options.totalPage as number);
    }
    function normalHandle(e: Event) {
      // 处理普通元素方法
      if (!e.target) {
        return;
      }
      const target: HTMLElement = e.target as HTMLElement;
      _this.jumpToPage(parseInt(target.dataset.pagerValue || "", 10));
    }
    // 绑定
    this.firstElem?.addEventListener("click", firstHandle);
    this.prevElem?.addEventListener("click", prevHandle);
    this.nextElem?.addEventListener("click", nextHandle);
    this.lastElem?.addEventListener("click", lastHandle);
    this.normalElem.forEach((elem) => {
      elem.addEventListener("click", normalHandle);
    });
  }
  // 跳转页面
  public jumpToPage(pageNum: number) {
    // 安全监测
    pageNum = pageNum < 1 ? 1 : pageNum;
    pageNum =
      pageNum > (this.options.totalPage as number)
        ? (this.options.totalPage as number)
        : pageNum;
    this.currentPage = pageNum;
    this.setPath();
    this.calNumberScope();
    this.updateDomContent();
    this.setButtonAuthority();
  }
  protected setPath() {
    if (this.options.pageQuery) {// 如果存在查询参数
      if (this.currentPage === 1) {// 如果当前跳转到首页
        location.pathname = this.rootPath;
      } else {// 默认情况
        let queryStr = this.options.pageQuery + this.currentPage;
        location.pathname = location.pathname + "/" + encodeURIComponent(queryStr);// 拼接路径
      }
    }
  }
  // 为一批元素添加样式
  protected addElemStyle(styleName: string, ...elems: (Element | undefined)[]) {
    elems.forEach(elem => {
      elem?.classList.add(styleName);
    });
  }
  // 为一批元素移除样式
  protected removeElemStyle(styleName: string, ...elems: (Element | undefined)[]) {
    elems.forEach(elem => {
      elem?.classList.remove(styleName);
    });
  }
}

